﻿/*
 * Created by SharpDevelop.
 * User: Intel
 * Date: 24.01.2014
 * Time: 11:45
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections;
using System.Collections.Generic;
using MySql.Data.MySqlClient;
using Region.Utils;
using Region.Reports;
namespace Region
{


    /// <summary> Класс Report обеспечивает логику работы с распоряжениями </summary>
  [DBObject(Table = "report", PrimaryKeyPole = "ReportID")]
  public partial class Report : DBObject
  {
    
    #region Поля
      [DBColumn]
      public Int32 ReportID { get; set; }
      [DBColumn]
      public Int32 OtdelID { get; set; }
      [DBColumn]
      public Int32 RaionID { get; set; }
      [DBColumn]
      public Int32 UserID { get; set; }
      [DBColumn]
      public Int32 ReportTemplateID { get; set; }
      [DBColumn(PoleType = EPoleType.RegionDate)]
      public RegionDate Date { get; set; }
      [DBColumn(PoleType = EPoleType.RegionDate)]
      public RegionDate Start { get; set; }
      [DBColumn(PoleType = EPoleType.RegionDate)]
      public RegionDate End { get; set; }
    #endregion
    /*class TReportData
    {
      public Boolean Edit;
      public String Table;
      public String Row;
      public String Column;
      public String Value;
    }
    Dictionary<String, TReportData> ReportData = new Dictionary<String, TReportData>();*/

    public Engine Engine { get{return m_engine;}}
    protected Dictionary<String, Boolean> m_Tables = new Dictionary<String, Boolean>();
    
    protected Dictionary<String, Dictionary<String, Boolean>> m_Rows = new Dictionary<String, Dictionary<String, Boolean>>();
    protected Dictionary<String, Dictionary<String, Boolean>> m_Cols = new Dictionary<String, Dictionary<String, Boolean>>();
    protected Dictionary<String, Dictionary<String, Boolean>> m_ObjectTypes = new Dictionary<String, Dictionary<String, Boolean>>();
    //Table-Row-Col-Value
    protected Dictionary<String, Dictionary<String, Dictionary<String, String>>> m_Cell = new Dictionary<String, Dictionary<String, Dictionary<String, String>>>();
    //Table-Row-Col-ObjectType-ID
    protected Dictionary<String, Dictionary<String, Dictionary<String,Dictionary<String, List<Int32>>>>> m_CellList = new Dictionary<String, Dictionary<String, Dictionary<String, Dictionary<String,List<Int32>>>>>();
    public IEnumerable<String> getTables() { return m_Tables.Keys; }
    public IEnumerable<String> getRows(String Table) { return m_Rows[Table].Keys; }
    public IEnumerable<String> getCols(String Table) { return m_Cols[Table].Keys; } 
    //public Dictionary<String, Dictionary<String, Dictionary<String, List<Int32>>>> CellList = new Dictionary<String, Dictionary<String, Dictionary<String, List<Int32>>>>();
    Boolean ReportLoad = false;
    Boolean ReportEdit = false;
    public void Clear()
    {
        ReportLoad = false;
        ReportEdit = true;
        m_Tables.Clear();
        m_Rows.Clear();
        m_Cols.Clear();
        m_Cell.Clear();
    }
    public void SetValue(String Table,String Row, String Col, String Value)
    {
        m_Tables[Table] = true;
        if (!m_Rows.ContainsKey(Table))
            m_Rows[Table] = new Dictionary<String, Boolean>();
        m_Rows[Table][Row] = true;
        if (!m_Cols.ContainsKey(Table))
            m_Cols[Table] = new Dictionary<String, Boolean>();
        m_Cols[Table][Col] = true;
        if (!m_Cell.ContainsKey(Table))
            m_Cell[Table] = new Dictionary<String, Dictionary<String, String>>();
        if (!m_Cell[Table].ContainsKey(Row))
            m_Cell[Table][Row] = new Dictionary<String, String>();
        m_Cell[Table][Row][Col] = Value;
        ReportLoad = true;
        ReportEdit = true;
    }
    public void SetCellList<RegionObject>(String Table, String Row, String Col, List<RegionObject> List)
        where RegionObject:DBObject
    {
        if (List == null)
            return;
        String ObjectType = typeof(RegionObject).Name;
        m_Tables[Table] = true;
        if (!m_Rows.ContainsKey(Table))
            m_Rows[Table] = new Dictionary<String, Boolean>();
        m_Rows[Table][Row] = true;
        if (!m_Cols.ContainsKey(Table))
            m_Cols[Table] = new Dictionary<String, Boolean>();
        m_Cols[Table][Col] = true;
        if (!m_ObjectTypes.ContainsKey(Table))
            m_ObjectTypes[Table] = new Dictionary<String, Boolean>();
        m_ObjectTypes[Table][ObjectType] = true;

        if (!m_CellList.ContainsKey(Table))
            m_CellList[Table] = new Dictionary<String, Dictionary<String, Dictionary<String, List<Int32>>>>();
        if (!m_CellList[Table].ContainsKey(Row))
            m_CellList[Table][Row] = new Dictionary<String, Dictionary<String, List<Int32>>>();
        if (!m_CellList[Table][Row].ContainsKey(ObjectType))
            m_CellList[Table][Row][Col] = new Dictionary<String, List<Int32>>();
        var ListID = new List<Int32>();
        foreach (RegionObject obj in List)
            ListID.Add((Int32)obj.PKValue);
        m_CellList[Table][Row][Col][ObjectType] = ListID;
        ReportLoad = true;
        ReportEdit = true;
    }
    public String GetValue(String Table,String Row, String Col)
    {
        if (!ReportLoad)
            LoadReportData();
        if (m_Cell.ContainsKey(Table) && m_Cell[Table].ContainsKey(Row) && m_Cell[Table][Row].ContainsKey(Col))
            return m_Cell[Table][Row][Col];
        return "";
    }
    public List<Int32> GetCellLIst(String Table, String Row, String Col,String ObjectType)
    {
        if (!ReportLoad)
            LoadReportData();
        if (m_CellList.ContainsKey(Table) && m_CellList[Table].ContainsKey(Row) && m_CellList[Table][Row].ContainsKey(Col) && m_CellList[Table][Row][Col].ContainsKey(ObjectType))
            return m_CellList[Table][Row][Col][ObjectType];
        return new List<Int32>();
    }
      public void LoadReportData()
    {
        Clear();
        SQLResult r = m_engine.SQLSelect("SELECT * FROM reportdata WHERE ReportID=@ReportID", new SQLParam() { { "@ReportID", PKValue } });
        for (int i = 0; i < r.Count; i++)        
            SetValue((String)r[i]["Table"], (String)r[i]["Row"], (String)r[i]["Column"], (String)r[i]["Value"]);
        ReportEdit = false;
        ReportLoad = true;
    }
    void SaveReportData()
    {
        if (!ReportEdit)
            return;
        SQLParam Param2 = new SQLParam();
        Param2["@ReportID"] = ReportID;
        m_engine.SQLEdit("DELETE FROM `reportdata` WHERE (`ReportID` = @ReportID)", Param2);
        if (!ReportLoad)
            return;
        List<String> V = new List<String>();
        Int32 N = 1;
        SQLParam Param = new SQLParam();
        foreach (String Table in m_Tables.Keys)
            if (m_Rows.ContainsKey(Table) && m_Cols.ContainsKey(Table))
                foreach (String Row in m_Rows[Table].Keys)
                    foreach (String Col in m_Cols[Table].Keys)
                    {
                        V.Add("(@ReportID" + N + ", @Table" + N + ", @Row" + N + ", @Column" + N + ", @Value" + N + ")");
                        Param["@ReportID" + N] = ReportID;
                        Param["@Table" + N] = Table;
                        Param["@Row" + N] = Row;
                        Param["@Column" + N] = Col;
                        Param["@Value" + N] = GetValue(Table, Row, Col);
                        N++;
                    }
        if (V.Count > 0) 
            m_engine.SQLEdit("INSERT INTO `reportdata` (`ReportID`,`Table`,`Row`,`Column`,`Value`) VALUES " + String.Join(", ", V.ToArray()), Param);  
    }
    void SaveReportList()
    {
        if (!ReportEdit)
            return;
        SQLParam Param2 = new SQLParam();
        Param2["@ReportID"] = ReportID;
        m_engine.SQLEdit("DELETE FROM `reportdatalist` WHERE (`ReportID` = @ReportID)", Param2);
        if (!ReportLoad)
            return;
        List<String> V = new List<String>();
        Int32 N = 1;
        SQLParam Param = new SQLParam();
        foreach (String Table in m_Tables.Keys)
            if (m_Rows.ContainsKey(Table) && m_Cols.ContainsKey(Table) && m_ObjectTypes.ContainsKey(Table))
                foreach (String Row in m_Rows[Table].Keys)
                    foreach (String Col in m_Cols[Table].Keys)                        
                        foreach (String ObjectType in m_ObjectTypes[Table].Keys)
                            foreach (Int32 ID in GetCellLIst(Table, Row, Col, ObjectType))
                            {
                                V.Add("(@RID" + N + ", @T" + N + ", @R" + N + ", @C" + N + ", @OT" + N + ", @ID" + N + ")");
                                Param["@RID" + N] = ReportID;
                                Param["@T" + N] = Table;
                                Param["@R" + N] = Row;
                                Param["@C" + N] = Col;
                                Param["@OT" + N] = ObjectType;
                                Param["@ID" + N] = ID;
                                N++;
                                if (N > 1000)// промежуточное сохранение так как размер отчёта может достигать более миллиона строк
                                {
                                    m_engine.SQLEdit("INSERT INTO `reportdatalist` (`ReportID`,`Table`,`Row`,`Column`,`ObjectType`,`ObjectID`) VALUES " + String.Join(", ", V.ToArray()), Param);
                                    N = 1;
                                    V = new List<String>();
                                    Param = new SQLParam();
                                }
                            }
        if (V.Count > 0)
            m_engine.SQLEdit("INSERT INTO `reportdatalist` (`ReportID`,`Table`,`Row`,`Column`,`ObjectType`,`ObjectID`) VALUES " + String.Join(", ", V.ToArray()), Param);
    }
      #region Переопределённые методы DBObject
    public override bool save()
    {
        SaveReportData();
        SaveReportList();
        return base.save();
    }
    public override bool isEdit()
    {
        return ReportEdit || base.isEdit();
    }
    public override bool read(MySqlConnection RegionDB=null)
    {
      if (!base.read(RegionDB)) return false;     
      return true;
    }
    /// <summary>Не редактируемые поля. доступны только для администратор</summary>
    static private Dictionary<String, bool> Access_NoEdit = new Dictionary<String, bool>() { { "RasporID", true }, { "RasporNum", true }, { "RasporYear", true }, { "StatusVip", true }, { "RucPodpis", true }, { "NachPodpis", true } };
    /// <summary>Поля закрываемые подписью</summary>
    static private Dictionary<String, bool> Access_BasePoles = new Dictionary<String, bool>() { { "Date", true }, { "CheckDoc", true }, { "CheckGo", true }, { "CheckPlan", true }, { "CheckLicen", true }, { "Pred", true }, { "OsnovID", true }, { "OtdelID", true }, { "IspUserID", true }, { "KontID", true }, { "TP", true }, { "Start", true }, { "End", true }, { "IspInfo", true }, { "ExpertsInfo", true }, { "TargetInfo", true }, { "TaskInfo", true }, { "OsnovInfo", true }, { "MKontrInfo", true }, { "AReglamInfo", true }, { "PDocInfo", true }, { "RucComment", true }, { "NachComment", true }, { "Action_StatusVip", true }, { "Action_RucPodpis", true }, { "Action_NachPodpis", true } };
    public override bool poleCheck(String PoleName, Object Value) { return true; }
    public override bool poleAccess(String PoleName)
    {
        return false;//Нет явынх править занчит надо запретить            
    }
    #endregion
    
    public delegate bool ProcessReport(Engine engine, Report report, TaskManager.Task task);
    public Report(Engine engine, Int32 ReportID)
          : base(engine, ReportID)
    {
    }
    bool loadHeader = false;
    ReportProcessor.ReportHeader<Report, String,ColHeaderAttribute> HeaderColTitle;
    ReportProcessor.ReportHeader<Report, String,RowHeaderAttribute> HeaderRowTitle;
    ReportProcessor.ReportHeader<Report, IHeaderInfo, ColHeaderAttribute> HeaderCol;
    ReportProcessor.ReportHeader<Report, IHeaderInfo, RowHeaderAttribute> HeaderRow;
    void loadHeaderInfo()
    {
        if (loadHeader)
            return;
        HeaderColTitle = new Reports.ReportProcessor.ReportHeader<Report,String,ColHeaderAttribute>(this);
        HeaderRowTitle = new Reports.ReportProcessor.ReportHeader<Report,String,RowHeaderAttribute>(this);
        HeaderCol = new Reports.ReportProcessor.ReportHeader<Report,IHeaderInfo,ColHeaderAttribute>(this);
        HeaderRow = new Reports.ReportProcessor.ReportHeader<Report,IHeaderInfo,RowHeaderAttribute>(this);
        String reportClass = m_engine.ReportTemplateClass[ReportTemplateID];
        HeaderColTitle.Process(reportClass);
        HeaderRowTitle.Process(reportClass);
        HeaderCol.Process(reportClass);
        HeaderRow.Process(reportClass);
        loadHeader = true;            
    }  
    public IHeaderInfo getHeaderCol(String Table,String Col)
    {
        if (!loadHeader)
            loadHeaderInfo();
        IHeaderInfo hi = null;
        hi = HeaderCol.getHeader(Table,Col);
        if (hi==null)
        {
            String ColTitle = HeaderColTitle.getHeader(Table,Col);            
            var newHi = new HeaderInfo();
            newHi.Name = Col;
            if (ColTitle==null)
                newHi.Title = Col;
            else                
                newHi.Title = ColTitle;
            newHi.ParentName = null;
            hi = newHi;
        }
        return hi;
    }
    public String getHeaderColTitle(String Table, String Col)
    {
        return getHeaderCol(Table, Col).Title;
    }
    public IHeaderInfo getHeaderRow(String Table, String Row)
    {
        if (!loadHeader)
            loadHeaderInfo();
        IHeaderInfo hi = null;
        hi = HeaderRow.getHeader(Table, Row);
        if (hi == null)
        {
            String ColTitle = HeaderRowTitle.getHeader(Table, Row);
            var newHi = new HeaderInfo();
            newHi.Name = Row;
            if (ColTitle == null)
                newHi.Title = Row;
            else
                newHi.Title = ColTitle;

            newHi.ParentName = null;
            hi = newHi;
        }
        return hi;
    }
    public String getHeaderRowTitle(String Table, String Row)
    {
        return getHeaderRow(Table, Row).Title;
    }
    // Вычислить данные отчёта
    public void Process()
    {
        String reportClass = m_engine.ReportTemplateClass[ReportTemplateID];
        var info = new ReportProcessor.ReportResultInfo<Report,String>(this);
        //Протоколы
        var infoProtokol = new ReportProcessor.ReportProccessInfo<Report, Protokol>(this);
        infoProtokol.Process(reportClass, (list) => {
            var l = new ProtokolList(m_engine);
            l.Filter();
            //m_engine.preLoadRaspor(l);
            for (Int32 i = 0; i < l.NumLines; i++)
                list.Add(m_engine.getProtokol(l.getLine(i).ProtokolID));
        });
        info.setInfo(infoProtokol);
        //Распоряжения
        var infoRaspor = new ReportProcessor.ReportProccessInfo<Report, Raspor>(this);
        infoRaspor.Process(reportClass, (list) =>
        {
            var l = new RasporList(m_engine);
            l.Filter();
            m_engine.preLoadRaspor(l);
            for (Int32 i = 0; i < l.NumLines; i++)
                list.Add(m_engine.getRaspor(l.getLine(i).RasporID));
        });
        info.setInfo(infoRaspor);
        // Вывести результаты
        info.Process(reportClass, SetValue, (String Table, String Row, String Col, Reports.IResultDataInfo Info) =>
        {
            SetCellList(Table, Row, Col, Info.getList<Protokol>());
            SetCellList(Table, Row, Col, Info.getList<Raspor>());
        });
    }
    public class HeaderShowInfo
    {
        public Region.Reports.IHeaderInfo info;
        public Int32 Depth = 0;
        public Int32 CountAllChilds = 0;
        public List<String> Childs = new List<String>();
    }
    delegate Region.Reports.IHeaderInfo getHeaderInfo(String HeaderName);
    void ProcessDepth(String HeaderName, Dictionary<String, HeaderShowInfo> HSI)
    {
        if (HeaderName == null)
            HeaderName = "";
        Int32 Depth = 0;
        Int32 CountAllChilds = 0;
        if (HSI[HeaderName].Childs.Count == 0)
            CountAllChilds = 1;
        else
            foreach (String ChildHeader in HSI[HeaderName].Childs)
            {
                ProcessDepth(ChildHeader, HSI);
                if (Depth < HSI[ChildHeader].Depth)
                    Depth = HSI[ChildHeader].Depth;
                CountAllChilds += HSI[ChildHeader].CountAllChilds;
            }

        HSI[HeaderName].Depth = Depth + 1;
        HSI[HeaderName].CountAllChilds = CountAllChilds;
    }
    void AddHeader( String HeaderName, Dictionary<String, HeaderShowInfo> HSI, getHeaderInfo getHI)
    {
        HeaderName = HeaderName == null ? "" : HeaderName;
        if (!HSI.ContainsKey(HeaderName))
        {
            HSI[HeaderName] = new HeaderShowInfo();
            if (HeaderName != "")
                HSI[HeaderName].info = getHI(HeaderName);
        }
        if (HSI[HeaderName].info != null)
        {
            String ParentName = HSI[HeaderName].info.ParentName;
            if (ParentName == null)
                ParentName = "";
            AddHeader(ParentName, HSI, getHI);
            if (!HSI[ParentName].Childs.Contains(HeaderName))
            {
                HSI[ParentName].Childs.Add(HeaderName);

            }

        }
    }
    void HSItoList(String HeaderName,Dictionary<String, HeaderShowInfo> HSI,List<String> Headers)
    {
        if (HeaderName == null)
            HeaderName = "";
        if (HSI[HeaderName].Childs.Count == 0)
            Headers.Add(HeaderName);
        else
            foreach (String ChildHeader in HSI[HeaderName].Childs)
                HSItoList(ChildHeader, HSI, Headers);
    }
    public void ProcessTable(String Table, IDictionary<string, object> ViewData)
    {
        var ColHSI = new Dictionary<String, HeaderShowInfo>();
        var RowHSI = new Dictionary<String, HeaderShowInfo>();
        var Cols = new List<String>();
        var Rows = new List<String>();
        foreach (String Col in getCols(Table))
            AddHeader( Col, ColHSI, (col) => getHeaderCol(Table, col));
        foreach (String Row in getRows(Table))
            AddHeader(Row, RowHSI, (row) => getHeaderRow(Table, row));
        ProcessDepth(null, ColHSI);
        ProcessDepth(null, RowHSI);
        HSItoList(null, ColHSI, Cols);
        HSItoList(null, RowHSI, Rows);
        ViewData["ColHSI"] = ColHSI;
        ViewData["RowHSI"] = RowHSI;
        ViewData["Cols"] = Cols;
        ViewData["Rows"] = Rows;
    }
  }
  public class ReportList
  {
    public struct Line
    {
      public Int32 ReportID;
      public Int32 OtdelID;
      public Int32 RaionID;
      public Int32 UserID;
      public Int32 ReportTemplateID;
      public RegionDate Date;
      public RegionDate Start;
      public RegionDate End;
    }
    private Engine m_engine;
    private List<Line> m_lines;
    private Dictionary<String, Object> m_wheres;
    public Line getLine(Int32 l) { return this.m_lines[l]; }
    public Int32 NumLines { get { return m_lines.Count; } }
    private Int32 m_FullLines;
    public Int32 FullLines { get { return m_FullLines; } }    
    public ReportList(Engine engine)
    {
        m_engine = engine;
        m_lines = new List<Line>();
        m_wheres = new Dictionary<String, Object>();
    }
    public bool clearWhere()
    {
        m_wheres = new Dictionary<String, Object>();
        return true;
    }
    public bool setWhere(String Where, Object Value)
    {
        m_wheres[Where] = Value;
        return true;
    }
    public bool Filter()
    {
        List<String> Tables = new List<String>();
        List<String> Poles = new List<String>();
        List<String> Wheres = new List<String>();
        List<String> OrderBy = new List<String>();
        SQLParam Params = new SQLParam();
        //Params["@Param"]=100;
        Poles.Add("report.ReportID");
        Poles.Add("report.OtdelID");
        Poles.Add("report.RaionID");
        Poles.Add("report.UserID");
        Poles.Add("report.ReportTemplateID");
        Poles.Add("report.Date");
        Poles.Add("report.Start");
        Poles.Add("report.End");
        Tables.Add("report");
        Wheres.Add("1");
        OrderBy.Add("report.Date DESC");
        Int32 ReportID, ParentOtdelID, RasporYear, RasporNumStart, RasporNumEnd, UserID, LineInPage, Page, CheckPlan;
        String[] DatePoles = { "Date", "Start", "End" };
        for (Int32 i = 0; i < DatePoles.Length; i++)
        {
            String Pole = DatePoles[i];
            if (m_wheres.ContainsKey(Pole + "Start"))
            { 
              RegionDate date = m_wheres[Pole + "Start"] as RegionDate;
              if (date!=null && !(date.Empty))
              {
                Wheres.Add("report." + Pole + " >= @" + Pole + "Start");
                Params["@" + Pole + "Start"] = date.getRegionDate();
              }
            }
            if (m_wheres.ContainsKey(Pole + "End"))
            {
              RegionDate date = m_wheres[Pole + "End"] as RegionDate;
              if (date!=null && !(date.Empty))
              {
                Wheres.Add("report." + Pole + " < @" + Pole + "End");
                Params["@" + Pole + "End"] = date.getRegionDate();
              }
            }
        }
        if (m_wheres.ContainsKey("ReportID") && m_wheres["ReportID"] != null && Int32.TryParse(m_wheres["ReportID"].ToString(), out ReportID) && ReportID>0)
        {
            Wheres.Add("report.ReportID=@ReportID");
            Params["@ReportID"] = ReportID;
        }
        if (m_wheres.ContainsKey("ParentOtdelID") && m_wheres["ParentOtdelID"] != null && Int32.TryParse(m_wheres["ParentOtdelID"].ToString(), out ParentOtdelID) && ParentOtdelID>0)
        {
            Tables.Add("INNER JOIN otdel_otdel ON otdel_otdel.OtdelID=report.OtdelID");
            Wheres.Add("otdel_otdel.ParentOtdelID=@ParentOtdelID");
            Params["@ParentOtdelID"] = ParentOtdelID;
        }
        if (m_wheres.ContainsKey("UserID") && m_wheres["UserID"] != null && Int32.TryParse(m_wheres["UserID"].ToString(), out UserID) && UserID>0)
        {
            Wheres.Add("raspor.UserID=@UserID");
            Params["@UserID"] = UserID;
        }

        String OrderBySQL = "";
        String LimitSQL = "";        
        if (!(m_wheres.ContainsKey("IgnorePage") && (Boolean)m_wheres["IgnorePage"]))
          if (m_wheres.ContainsKey("LineInPage") && m_wheres["LineInPage"] != null && Int32.TryParse(m_wheres["LineInPage"].ToString(), out LineInPage) && LineInPage > 1)
        {
            if (!m_wheres.ContainsKey("Page") || m_wheres["Page"] == null || !Int32.TryParse(m_wheres["Page"].ToString(), out Page)) Page = 1;
            Int32 Start = (Page - 1) * LineInPage;
            LimitSQL = "LIMIT " + Start + ", " + LineInPage + " ";
        }

        if (OrderBy.Count > 0) OrderBySQL = "ORDER BY " + String.Join(", ", OrderBy.ToArray());
        String SQL = String.Format("SELECT SQL_CALC_FOUND_ROWS {0} FROM {1} WHERE ({2}) {3} {4}",
            String.Join(", ", Poles.ToArray()),
            String.Join(" ", Tables.ToArray()),
            String.Join(") AND (", Wheres.ToArray()),
            OrderBySQL, LimitSQL);
        SQLResult r = m_engine.SQLSelect(SQL,Params);
        SQLResult r2 = m_engine.SQLSelect("SELECT FOUND_ROWS() AS Count",new SQLParam());                        
        m_FullLines = (Int32)(Int64)r2[0]["Count"];
        m_lines.Clear();
        for (Int32 i = 0; i < r.Count; i++)            
        {
            Line l = new Line();
            l.ReportID = (Int32)r[i]["ReportID"];
            l.OtdelID = (Int32)r[i]["OtdelID"];
            l.RaionID = (Int32)r[i]["RaionID"];
            l.UserID = (Int32)r[i]["UserID"];
            l.ReportTemplateID = (Int32)r[i]["ReportTemplateID"];
            l.Date = Engine.IntToRegionDate((Int32)r[i]["Date"]);
            l.Start = Engine.IntToRegionDate((Int32)r[i]["Start"]);
            l.End = Engine.IntToRegionDate((Int32)r[i]["End"]);
            m_lines.Add(l);
        }
        return true;
    }    
  }
  public partial class Engine
  {
      /// <summary> Список открытых распояжений </summary>
      private Dictionary<Int32, Report> l_Report;
      /// <summary> Получить распоряжение по его идентификатору</summary><param name="RasporID">ИД Распоряжения</param><returns>Объект распоряжения</returns>
      public Report getReport(Int32 ReportID)
      {
          if (l_Report == null) l_Report = new Dictionary<Int32, Report>();
          if (l_Report.ContainsKey(ReportID)) return (Report)l_Report[ReportID];
          Report report = new Report(this, ReportID);
          l_Report[ReportID] = report;
          return report;
      }
      /// <summary>Создать новое распоряжение</summary><param name="BaseRasporID">Идентификатор распоряжения на основе которого создаётся распоряжение</param><returns>Идентификатор нового расоряжения</returns>
      public Int32 newReport(Int32 ReportTemplateID)
      {
          if (!CurrentUser.isAccess("EditReport")) return 0;// Пользователь неимеет права удалять распоряжения      
          SQLParam Param = new SQLParam();
          Param["@Date"] = RegionDateToInt(DateTime.Now);
          Param["@Start"] = RegionDateToInt(new DateTime(DateTime.Now.Year,1,1));
          Param["@End"] = RegionDateToInt(new DateTime(DateTime.Now.Year+1,1,1));
          Param["@UserID"] = CurrentUser.UserID;
          Param["@OtdelID"] = CurrentUser.OtdelID;
          MySqlCommand cmd;
          SQLEdit(@"INSERT INTO raspor(ReportTemplateID,OtdelID,UserID,Date,Start,End) VALUES (@ReportTemplateID, @OtdelID, @UserID, @Date, @Start, @End) ", Param, out cmd);
          return (Int32)cmd.LastInsertedId;
      }
      /// <summary>Удалить распоряжение</summary><param name="RasporID">ИД распоряжения</param><returns>true - если распоряжение было удалено</returns>
      public bool delReport(Int32 ReportID)
      {
          Report report = getReport(ReportID);
          if (!CurrentUser.isAccess("EditReport")) return false;// Пользователь неимеет права удалять распоряжения            
          if (!CurrentUser.isAccess("Admin") && CurrentUser.OtdelID != report.OtdelID && !Otdels[CurrentUser.OtdelID].isSubOtdel(report.OtdelID)) return false;//нельзя удалить черновик другово отдела
          SQLParam Param = new SQLParam();
          Param["ReportID"] = ReportID;
          //Удалить само распоряжение
          Int32 N = SQLEdit("DELETE FROM report WHERE ReportID=@ReportID", Param);
          if (N == 1) // Распоряжение действительно удалено. 
          {
              l_Report.Remove(ReportID);
              return true;
          }
          return false;
      }
      public Dictionary<String, Type> getReportProcessors()
      {
          var table = new Dictionary<String, Type>();
          foreach(var a in AppDomain.CurrentDomain.GetAssemblies())
              foreach(var t in a.GetTypes())
              {
                  var att = Attribute.GetCustomAttribute(t, typeof(Reports.ProcessorAttribute), true);
                  if(att!=null)
                  {
                      var Name = ((Reports.ProcessorAttribute)att).TemplateClass;
                      if (Name==null)
                          Name = t.Name;
                      table[Name] = t;
                  }
              }
          return table;
      }
  }
  
}
